/* radix.h - radix tree implementation for routing table */

/* Copyright 2001-2004 Wind River Systems, Inc. */

/*
 * Copyright (c) 1988, 1989, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)radix.h	8.2 (Berkeley) 10/31/94
 * $FreeBSD: src/sys/net/radix.h,v 1.16.2.1 2000/05/03 19:17:11 wollman Exp $
 */

/*
modification history
--------------------
01l,07apr05,spm  fixed memory leak from netmask storage (SPR #97721)
01k,02jul04,vvv  fixed warning
01j,20nov03,niq  Remove copyright_wrs.h file inclusion
01i,05nov03,cdw  Removal of unnecessary _KERNEL guards.
01h,04nov03,rlm  Ran batch header path update for header re-org.
01g,03nov03,rlm  Removed wrn/coreip/ prefix from #includes for header re-org.
01f,06aug03,niq  Merge from Accordion into Base6 Iteration 1 branch
01e,10jun03,vvv  include netVersion.h
01h,04mar03,niq  Move rn_refines from radix.c to route.c to eliminate
                 dependency
01g,02dec02,spm  merged from WINDNET_IPV6-1_0-FCS label (ver 01d,11oct02,ham)
01f,17oct02,spm  replaced private globals to permit multiple tree instances
01e,09oct02,spm  changed for Patricia tree RIB implementation: 
                 updated node type and added fields for cleanup routine
01d,31jul02,spm  merged from WINDNET_IPV6-2_0-BETA label
01c,29may02,spm  updated from Router Stack 1.0: alternate multipath, skip
                 routes with disabled interface
01b,01feb02,nee  changing prototype for rn_delete
01a,08sep01,qli  1st round of porting
*/

#ifndef _RADIX_H_
#define	_RADIX_H_

#ifdef __cplusplus
extern "C" {
#endif
     
#include <netVersion.h>

struct ptRibHead;

/*
 * Radix search tree node layout.
 */

struct radix_node {
	struct	radix_mask *rn_mklist;	/* list of masks contained in subtree */
	struct	radix_node *rn_parent;	/* parent */
	short	rn_bit;			/* bit offset; -1-index(netmask) */
	char	rn_bmask;		/* node: mask for bit test*/
	u_char	rn_flags;		/* enumerated next */
#define RNF_NORMAL	1		/* leaf contains normal route */
#define RNF_ROOT	2		/* leaf is root leaf for tree */
#define RNF_ACTIVE	4		/* This node is alive (for rtfree) */		
#define RNF_NONOP 16		/* This node is through an interface which is non-operational eg. down*/
	union {
		struct {			/* leaf only data: */
			caddr_t	rn_Key;		/* object of search */
			caddr_t	rn_Mask;	/* netmask, if present */
			struct	radix_node *rn_Dupedkey;
		} rn_leaf;
		struct {			/* node only data: */
			int	rn_Off;		/* where to start compare */
			struct	radix_node *rn_L;/* progeny */
			struct	radix_node *rn_R;/* progeny */
		} rn_node;
	}		rn_u;
#ifdef RN_DEBUG
	int rn_info;
	struct radix_node *rn_twin;
	struct radix_node *rn_ybro;
#endif
};

#define	rn_dupedkey	rn_u.rn_leaf.rn_Dupedkey
#define	rn_key		rn_u.rn_leaf.rn_Key
#define	rn_mask		rn_u.rn_leaf.rn_Mask
#define	rn_offset	rn_u.rn_node.rn_Off
#define	rn_left		rn_u.rn_node.rn_L
#define	rn_right	rn_u.rn_node.rn_R

/*
 * Annotations to tree concerning potential routes applying to subtrees.
 */

struct radix_mask {
	short	rm_bit;			/* bit offset; -1-index(netmask) */
	char	rm_unused;		/* cf. rn_bmask */
	u_char	rm_flags;		/* cf. rn_flags */
	struct	radix_mask *rm_mklist;	/* more masks to try */
	union	{
		caddr_t	rmu_mask;		/* the mask */
		struct	ptRouteNode *rmu_leaf;	/* for normal routes */
	}	rm_rmu;
	int	rm_refs;		/* # of references to this struct */
};

#define	rm_mask rm_rmu.rmu_mask
#define	rm_leaf rm_rmu.rmu_leaf		/* extra field would make 32 bytes */

typedef int walktree_f_t __P((struct radix_node *, void *));

#ifdef v /* XXX workaround for SPR 81215 */
#undef v
#endif 

struct radix_node_head {
	struct	radix_node *rnh_treetop;
	int	rnh_addrsize;		/* permit, but not require fixed keys */
	int	rnh_pktsize;		/* permit, but not require fixed keys */
	struct	radix_node *(*rnh_addaddr)	/* add based on sockaddr */
		__P((void *v, void *mask,
		     struct radix_node_head *head, struct radix_node nodes[]));
	struct	radix_node *(*rnh_addpkt)	/* add based on packet hdr */
		__P((void *v, void *mask,
		     struct radix_node_head *head, struct radix_node nodes[]));
	struct	radix_node *(*rnh_deladdr)	/* remove based on sockaddr */
		__P((void *v, void *mask, struct radix_node_head *head,struct radix_node *));
	struct	radix_node *(*rnh_delpkt)	/* remove based on packet hdr */
		__P((void *v, void *mask, struct radix_node_head *head));
	struct	radix_node *(*rnh_matchaddr)	/* locate based on sockaddr */
		__P((void *v, struct radix_node_head *head));
	struct	radix_node *(*rnh_lookup)	/* locate based on sockaddr */
		__P((void *v, void *mask, struct radix_node_head *head));
	struct	radix_node *(*rnh_matchpkt)	/* locate based on packet hdr */
		__P((void *v, struct radix_node_head *head));
	int	(*rnh_walktree)			/* traverse tree */
		__P((struct radix_node_head *head, walktree_f_t *f, void *w));
	int	(*rnh_walktree_from)		/* traverse tree below a */
		__P((struct radix_node_head *head, void *a, void *m,
		     walktree_f_t *f, void *w));
	void	(*rnh_close)	/* do something when the last ref drops */
		__P((struct radix_node *rn, struct radix_node_head *head));
	struct	radix_node rnh_nodes[3];	/* empty tree for common case */
        struct radix_node_head * pMaskHead;   /* storage for public masks */
        struct radix_mask * pMaskList;   /* storage for private masks */
        int trimSize;   /* length of last netmask, without trailing zeroes */
        int max_keylen;         /* size of address for protocol family */
};

/*
Argument for rn_match for receiving implicit flags in "flags" and the dst sockaddr in "dst"
Replaces the use of the precious v_arg as the dst sockaddr only."flags" can be used to select
a function pointer that applies to a corresponding flag.
*/
#ifdef RADIX_MPATH
typedef struct radix_node * (*radixFuncType)(struct radix_node *);
#endif

struct radix_arg {
	caddr_t dst;
	u_char flags;
#ifdef RADIX_MPATH
	radixFuncType radixFuncList[16];
#endif
};

#ifdef VIRTUAL_STACK
STATUS 	radixInit __P((void));
#endif
void	 rn_init __P((struct ptRibHead *));

int	 rn_inithead __P((void **, int, char *, char *));
IMPORT int	 rn_refines __P((void *, void *));
struct radix_node
	 *rn_addmask __P((struct radix_node_head *, void *, int, int,
                          int *, int)),
	 *rn_addroute __P((void *, void *, struct radix_node_head *,
			struct radix_node [2])),
	 *rn_delete __P((void *, void *, struct radix_node_head *,struct radix_node *)),
	 *rn_lookup __P((void *v_arg, void *m_arg,
		        struct radix_node_head *head)),
	 *rn_match __P((void *, struct radix_node_head *));

#ifdef __cplusplus
}
#endif

#endif /* _RADIX_H_ */
